package com.zxx.good.utils;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Splitter;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SpliceUtil {
    private SpliceUtil() {
    }


    public static <T> QueryWrapper search(String filters, String sorts, QueryWrapper<T> ew) {
        if (!StringUtils.isEmpty(sorts)) {
            String[] orderArray = sorts.split(",");
            List<String> strASC = new ArrayList();
            List<String> strDesc = new ArrayList();
            Arrays.stream(orderArray).forEach((s) -> {
                if (s.startsWith("+")) {
                    strASC.add(s.substring(1));
                } else if (s.startsWith("-")) {
                    strDesc.add(s.substring(1));
                }

            });
            if (strASC.size() > 0) {
                ew.orderByAsc(strASC.toArray(new String[0]));
            }

            if (strDesc.size() > 0) {
                ew.orderByDesc(strDesc.toArray(new String[0]));
            }
        } else {
            ew.orderBy(true, false, new String[]{"update_time"});
        }

        if (filters != null && !"".equals(filters)) {
            List<String[]> keyVals = (List) Splitter.on(";").omitEmptyStrings().trimResults().splitToList(filters).stream().map((token) -> {
                return StringUtils.split(token, "=", 2);
            }).collect(Collectors.toList());
            keyVals.forEach((keyVal) -> {
                String key = keyVal[0];
                String[] names = StringUtils.split(key, "_", 2);
                if (names.length != 2 && !"OR".equals(names[0])) {
                    throw new IllegalArgumentException(key + " is not a valid search filter name");
                } else {
                    String val = "";
                    if (keyVal.length > 1) {
                        val = StringUtils.trimToEmpty(keyVal[1]);
                    }

                    Operator operator = Operator.valueOf(names[0]);
                    List<String> vals = (List) Arrays.stream(val.split(",")).filter(StringUtils::isNotBlank).collect(Collectors.toList());
                    switch (operator) {
                        case EQ:
                            ew.eq(names[1], val);
                            break;
                        case NE:
                            ew.ne(names[1], val);
                            break;
                        case LIKE:
                            ew.like(names[1], val);
                            break;
                        case NOTLIKE:
                            ew.notLike(names[1], val);
                            break;
                        case GT:
                            ew.gt(names[1], val);
                            break;
                        case GE:
                            ew.ge(names[1], val);
                            break;
                        case LT:
                            ew.lt(names[1], val);
                            break;
                        case LE:
                            ew.le(names[1], val);
                            break;
                        case ISNULL:
                            ew.isNull(names[1]);
                            break;
                        case ISNOTNULL:
                            ew.isNotNull(names[1]);
                            break;
                        case IN:
                            ew.in(names[1], vals.toArray());
                            break;
                        case NOTIN:
                            ew.notIn(names[1], vals.toArray());
                            break;
                        case HAVING:
                            ew.having(names[1], new Object[]{val});
                            break;
                        case BETWEEN:
                            if (vals.isEmpty() || vals.size() != 2) {
                                throw new RuntimeException("BETWEEN Params is Empty.");
                            }

                            ew.between(names[1], Convert.convert(String.class, vals.get(0)), Convert.convert(String.class, vals.get(1)));
                            break;
                        case NOTBETWEEN:
                            if (vals.isEmpty() || vals.size() != 2) {
                                throw new RuntimeException("BETWEEN Params is Empty.");
                            }

                            ew.notBetween(names[1], Convert.convert(String.class, vals.get(0)), Convert.convert(String.class, vals.get(1)));
                            break;
                        case OR:
                            ew.or();
                            break;
                        case DATEBETWEEN:
                            ew.notBetween("DATE_FORMAT(" + names[1] + ",'%Y%m)')", Convert.convert(String.class, vals.get(0)), Convert.convert(String.class, vals.get(1)));
                    }

                }
            });
            return ew;
        } else {
            return ew;
        }
    }

    public static enum Operator {
        EQ,
        NE,
        GT,
        GE,
        LT,
        LE,
        BETWEEN,
        NOTBETWEEN,
        LIKE,
        NOTLIKE,
        ISNULL,
        ISNOTNULL,
        IN,
        NOTIN,
        HAVING,
        OR,
        DATEBETWEEN;

        private Operator() {
        }
    }
}
